﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using Se.Framework.Common.Data;

namespace Se.Framework.Common.Extentions
{
    public static class IEnumerableExtentions
    {
        public static int IndexOf(this IEnumerable items, object itemToSearch)
        {
            int index = -1, aux = 0;
            var enumerator = items.GetEnumerator();
            while (index == -1 && enumerator.MoveNext())
            {
                if (enumerator.Current.Equals(itemToSearch))
                    index = aux;
                aux++;
            }
            return index;
        }

        public static int IndexOf<T>(this IEnumerable<T> items, T itemToSearch)
        {
            return ((IEnumerable)items).IndexOf(itemToSearch);
        }

        public static IEnumerable ForEach(this IEnumerable items, Action<object> action)
        {
            foreach (var item in items)
            {
                action(item);
            }
            return items;
        }

        public static IEnumerable<T> Range<T>(this T firstItem, int count, Func<T> action)
        {
            yield return firstItem;
            count--;
            for (int i = 0; i < count; i++)
            {
                yield return action();
            }
        }

        public static IEnumerable<T> ForEach<T>(this IEnumerable<T> items, Action<T> action)
        {
            return (IEnumerable<T>)((IEnumerable)items).ForEach((obj) => { action((T)obj); });
        }

        public static int Count(this IEnumerable items)
        {
            int count = 0;
            var enumerator = items.GetEnumerator();
            while (enumerator.MoveNext())
            {
                count++;
            }
            return count;
        }

        public static object ElementAt(this IEnumerable items, int index)
        {
            int aux = 0;
            foreach (var item in items)
            {
                if (aux == index)
                    return item;

                aux++;
            }
            throw new IndexOutOfRangeException();
        }

        public static bool AreEquals(this IEnumerable items, IEnumerable secondCollection)
        {
            IEnumerable aux = secondCollection;
            if (aux.Count() != items.Count())
                return false;

            int index = 0;
            foreach (var item in aux)
            {
                if (!item.Equals(items.ElementAt(index)))
                {
                    return false;
                }
                index++;
            }
            return true;
        }

        public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> collecion, int pageSize)
        {
            int actualRecords = 0;
            int totalRecords = collecion.Count();
            while (totalRecords > actualRecords)
            {
                yield return collecion.Skip(actualRecords).Take(pageSize);
                actualRecords += pageSize;
            }
        }

        public static IDictionary<string, string> ToDictionary(this NameValueCollection source)   
        { 
            return source.Cast<string>()
                         .Select(s => new { Key = s, Value = source[s] })
                         .ToDictionary(p => p.Key, p => p.Value);
        }

        public static Queue<T> ToQueue<T>(this IEnumerable<T> collection)
        {
            return new Queue<T>(collection);
        }

        public static IEnumerable<Tto> Map<Tto>(this IEnumerable<object> list)
        {
            var mapper = ObjectRegistry.Current.Resolve<IMapper>();
            foreach (var item in list)
            {
                yield return mapper.Map<Tto>(item);
            }
        }
    }
}